/**
 * Author: Zane
 * Email: 873934580@qq.com
 * Date: 2023/6/12
 */
import { reactive, ref } from 'vue'
import { context } from './context'
import { getLibraryName } from './library'
import { error } from './util'
import type { IChannelModelField } from '@/model'

export type IRule = {
    id: string
    type: string
    field?: string
    label?: string
    // 是否选中状态
    active?: boolean
    children?: IRule[]
}
// 表单引用对象
const formRef = ref()

// 当前选中的目标组件
export const current = ref('')

// 根节点信息
export const RootNode = reactive<string[]>([])

// 上下文集合
export const contexts: { [key: string]: context } = {}

// 设置表单引用对象
export const setFormRef = (fRef: any) => {
    formRef.value = fRef.value
}

// 验证表单对象
export const check = async () => {
    if (formRef.value === undefined) {
        error('请设置表单信息')
        return false
    }
    try {
        await formRef.value.api.getFormRef().validate()
    } catch (e: any) {
        error('请完善表单信息')
        return false
    }

    return true
}

export const getFormData = () => {
    return formRef.value?.api.getFormData()
}

export const byId = (id: string): context => {
    return contexts[id] || undefined
}

// 插入指定位置类型
export const install = (type: string, index: number, parent?: any) => {
    const ctx = new context(type, getLibraryName(type))
    if (parent === undefined) {
        if (index === 0) {
            RootNode.unshift(ctx.id)
        } else if (RootNode.length === index) {
            RootNode.push(ctx.id)
        } else {
            RootNode.splice(index, 0, ctx.id)
        }
    } else {
        // 子级情况下
        const parentCtx = byId(parent)
        if (parentCtx === undefined) {
            console.error('异常节点')
            return
        }
        parentCtx.insert(ctx, index)
    }
    contexts[ctx.id] = ctx
    selectTarget(ctx.id)
    return ctx
}

/**
 * 根据数据结果插入
 * @param data
 */
export const installResults = (data: IChannelModelField) => {
    const ctx = new context(data.type)
    ctx.loadParserResults(data)
    RootNode.push(ctx.id)
    contexts[ctx.id] = ctx
}

// 选中目标
export const selectTarget = (id: string) => {
    for (const index in contexts) {
        const active = index === id
        contexts[index].setActive(active)
        if (active) current.value = id
    }
}

export const swap = (newIndex: number, oldIndex: number) => {
    const temp = RootNode[oldIndex]
    RootNode.splice(oldIndex, 1)
    RootNode.splice(newIndex, 0, temp)
}

// 向上移动
export const moveUp = (id: string, parent?: string) => {
    if (parent === undefined) {
        for (let i = 0; i < RootNode.length; i++) {
            if (i <= 0) continue
            if (RootNode[i] === id) {
                RootNode[i] = RootNode[i - 1]
                RootNode[i - 1] = id
                break
            }
        }
        return
    }

    byId(parent)?.moveUp(id)
}

// 向下移动
export const moveDown = (id: string, parent?: string) => {
    if (parent === undefined) {
        for (let i = 0; i < RootNode.length; i++) {
            if (i + 1 >= RootNode.length) break
            if (RootNode[i] === id) {
                RootNode[i] = RootNode[i + 1]
                RootNode[i + 1] = id
                break
            }
        }
        return
    }
    byId(parent)?.moveDown(id)
}

// 拷贝目标
export const copy = (id: string, parent?: string) => {
    let index = parent === undefined ? getRootNodeIndex(id) : byId(parent)?.getChildrenIndex(id)
    const ctx = byId(id)!
    install(ctx.type, (index || 0) + 1, parent)
}

// 删除目标
export const del = (id: string, parent?: string) => {
    if (parent === undefined) {
        let index = getRootNodeIndex(id)
        if (index !== undefined) RootNode.splice(index, 1)
    } else {
        byId(parent)?.del(id)
    }
    for (const key in contexts) {
        if (key === id) {
            delete contexts[key]
            break
        }
    }
    if (current.value === id) {
        current.value = ''
    }
}

export const delAll = () => {
    current.value = ''
    RootNode.length = 0
    for (const index in contexts) {
        delete contexts[index]
    }
}

/**
 * 根据ID获取根节点序号
 * @param id
 */
const getRootNodeIndex = (id: string) => {
    for (let i = 0; i < RootNode.length; i++) {
        if (RootNode[i] === id) {
            return i
        }
    }
}
